package net.jxtz.jxtzos.spider.process;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.jxtz.jxtzos.entity.spider.SpiderLogServe;
import net.jxtz.jxtzos.entity.spider.SpiderXinjianHousing;
import net.jxtz.jxtzos.mapper.redis.RedisMapper;
import net.jxtz.jxtzos.service.spider.SpiderXinjianHousingService;
import net.jxtz.jxtzos.spider.BaseSpiderProcessor;
import net.jxtz.jxtzos.spider.SpiderDefinition;
import net.jxtz.jxtzos.spider.SpiderFactory;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author lmh
 * @version 1.0
 * @date 2021-09-14 08:31
 */

@Component
@Slf4j
public class XinJianHousingInformationProcessor implements BaseSpiderProcessor {

    protected final CloseableHttpClient httpClient = HttpClients.createDefault();

    public final static String SPIDER_NAME = "xinJianHousing";

    protected final static int SECOND_SLEEP_TIME = 1;

    protected final static int MAX_PAGE = 50;

    public final static String CACHE_NAME = "cache.spider.process.XinJianHousingInformationProcessor";
    public final static String URL_PREFIX = "http://59.53.216.196/zt/House";

    private final RedisMapper redisMapper;

    private final SpiderXinjianHousingService spiderXinjianHousingService;

    private Long spiderLogId;

    public XinJianHousingInformationProcessor(RedisMapper redisMapper, SpiderXinjianHousingService spiderXinjianHousingService) {
        this.redisMapper = redisMapper;
        this.spiderXinjianHousingService = spiderXinjianHousingService;
        SpiderFactory instance = SpiderFactory.getInstance();
        instance.putSpiderProcess(SPIDER_NAME, this);
        instance.putSpiderDefinition(SPIDER_NAME, new SpiderDefinition("新建政府预售信息", SPIDER_NAME));

    }

    @Override
    public void start(SpiderLogServe spiderLogServe, SpiderDefinition spiderDefinition) {
        int startCount = spiderXinjianHousingService.count();
        spiderLogId = spiderLogServe.getId();
        int page = 0;
        boolean flag = true;
        String url = URL_PREFIX + "/ListPreSell?page=" + page + "&Place=&LicenceId=&Developer=&Project=&Date=";
        while (flag) {
            log.info("当前：" + page + "页");
            flag = process(url);
            page++;
            if (page >= MAX_PAGE) {
                flag = false;
            }
        }

        int endCount = spiderXinjianHousingService.count();
        int count = endCount - startCount;
        log.info("爬取完毕，更新总量：" + count);
        spiderLogServe.setCount(count);
        spiderLogServe.setExecute(true);
    }

    public boolean process(String url) {

        String s = httpClientInvoke(url);
        if (StringUtils.isBlank(s)) {
            return false;
        }
        Document indexDocument = Jsoup.parse(s);
        Element table = indexDocument.getElementsByTag("table").get(0).getElementsByTag("tbody").get(0);
        if (Objects.isNull(table)) {
            return false;
        }
        Elements tr = table.getElementsByTag("tr");
        List<SpiderXinjianHousing> list = new ArrayList<>();
        for (Element element : tr) {
            // 首页列表
            String preId = element.getElementsByTag("td").get(1).getElementsByTag("a").get(0).text();
            String devCompany = element.getElementsByTag("td").get(2).text();
            String projectName = element.getElementsByTag("td").get(3).getElementsByTag("a").get(0).text();
            String projectAreaName = element.getElementsByTag("td").get(4).text();
            String passTime = element.getElementsByTag("td").get(5).text();
            String caseId = element.getElementsByTag("td").get(6).getElementsByTag("a").get(0).attr("href");

            SpiderXinjianHousing xinjianHousing = new SpiderXinjianHousing();
            xinjianHousing.setPreId(preId);
            xinjianHousing.setDevCompany(devCompany);
            xinjianHousing.setProjectName(projectName);
            xinjianHousing.setProjectAreaName(projectAreaName);
            xinjianHousing.setPassTime(passTime);

            String detailsPage = URL_PREFIX + "/" + caseId;
            String saleStatus = "预售";
            detailsProcess(detailsPage, xinjianHousing, list, saleStatus);
        }

        saveCache(list);

        return true;
    }

    public void detailsProcess(String url, SpiderXinjianHousing spiderXinjianHousing, List<SpiderXinjianHousing> list, String saleStatus) {
        // 进入详情页
        String detail = httpClientInvoke(url);

        Document parse = Jsoup.parse(detail);
        Element houseTable = parse.getElementsByClass("house_table").get(0);
        Elements tr1 = houseTable.getElementsByTag("tr");
        String preId = tr1.get(1).getElementsByTag("td").get(1).text();
        String salePhone = tr1.get(1).getElementsByTag("td").get(3).text();
        String using = tr1.get(3).getElementsByTag("td").get(1).text();
        String landSource = tr1.get(3).getElementsByTag("td").get(3).text();
        String landArea = tr1.get(4).getElementsByTag("td").get(1).text();
        String landLevel = tr1.get(4).getElementsByTag("td").get(3).text();
        String occupationArea = tr1.get(5).getElementsByTag("td").get(1).text();
        String communityBuildArea = tr1.get(5).getElementsByTag("td").get(3).text();
        String plotRatio = tr1.get(6).getElementsByTag("td").get(1).text();
        String greenRatio = tr1.get(6).getElementsByTag("td").get(3).text();
        String buildDensity = tr1.get(7).getElementsByTag("td").get(1).text();
        String projectInvestment = tr1.get(7).getElementsByTag("td").get(3).text();
        String startProjectTime = tr1.get(8).getElementsByTag("td").get(1).text();
        String endProjectTime = tr1.get(8).getElementsByTag("td").get(3).text();
        String constructionUnit = tr1.get(9).getElementsByTag("td").get(1).text();
        String mappingUnit = tr1.get(9).getElementsByTag("td").get(3).text();
        // 批准销售住宅
        String approveHouseNumber = tr1.get(12).getElementsByTag("td").get(1).text();
        String approveHouseArea = tr1.get(12).getElementsByTag("td").get(2).text();
        // 批准销售商业
        String approveBusinessNumber = tr1.get(12).getElementsByTag("td").get(3).text();
        String approveBusinessArea = tr1.get(12).getElementsByTag("td").get(4).text();
        // 批准销售写字楼
        String approveOfficeNumber = tr1.get(12).getElementsByTag("td").get(5).text();
        String approveOfficeArea = tr1.get(12).getElementsByTag("td").get(6).text();
        // 批准销售车库车位
        String approveParkingNumber = tr1.get(12).getElementsByTag("td").get(7).text();
        String approveParkingArea = tr1.get(12).getElementsByTag("td").get(8).text();
        // 批准销售其他
        String approveOtherNumber = tr1.get(12).getElementsByTag("td").get(9).text();
        String approveOtherArea = tr1.get(12).getElementsByTag("td").get(10).text();

        // 可售住宅
        String inSaleHouseNumber = tr1.get(13).getElementsByTag("td").get(1).text();
        String inSaleHouseArea = tr1.get(13).getElementsByTag("td").get(2).text();
        // 可售商业
        String inSaleBusinessNumber = tr1.get(13).getElementsByTag("td").get(3).text();
        String inSaleBusinessArea = tr1.get(13).getElementsByTag("td").get(4).text();
        // 可售写字楼
        String inSaleOfficeNumber = tr1.get(13).getElementsByTag("td").get(5).text();
        String inSaleOfficeArea = tr1.get(13).getElementsByTag("td").get(6).text();
        // 可售车库车位
        String inSaleParkingNumber = tr1.get(13).getElementsByTag("td").get(7).text();
        String inSaleParkingArea = tr1.get(13).getElementsByTag("td").get(8).text();
        // 可售其他
        String inSaleOtherNumber = tr1.get(13).getElementsByTag("td").get(9).text();
        String inSaleOtherArea = tr1.get(13).getElementsByTag("td").get(10).text();

        // 已售住宅
        String outSaleHouseNumber = tr1.get(14).getElementsByTag("td").get(1).text();
        String outSaleHouseArea = tr1.get(14).getElementsByTag("td").get(2).text();
        // 已售商业
        String outSaleBusinessNumber = tr1.get(14).getElementsByTag("td").get(3).text();
        String outSaleBusinessArea = tr1.get(14).getElementsByTag("td").get(4).text();
        // 已售写字楼
        String outSaleOfficeNumber = tr1.get(14).getElementsByTag("td").get(5).text();
        String outSaleOfficeArea = tr1.get(14).getElementsByTag("td").get(6).text();
        // 已售车库车位
        String outSaleParkingNumber = tr1.get(14).getElementsByTag("td").get(7).text();
        String outSaleParkingArea = tr1.get(14).getElementsByTag("td").get(8).text();
        // 已售其他
        String outSaleOtherNumber = tr1.get(14).getElementsByTag("td").get(9).text();
        String outSaleOtherArea = tr1.get(14).getElementsByTag("td").get(10).text();

        // 楼栋数，楼栋详情
        Element houseTableFoot = parse.getElementsByClass("house_table").get(1);
        Element tr2 = houseTableFoot.getElementsByTag("tr").get(0);
        Element td = tr2.getElementsByTag("td").get(1);
        Elements a = td.getElementsByTag("a");
        for (Element element1 : a) {
            // 楼栋
            String text = element1.text();
            // 楼栋详情页链接
            String href = element1.attr("href");
            String url1 = URL_PREFIX + "/" + href;
            String s1 = httpClientInvoke(url1);

            // 进入楼栋详情页
            Document parse1 = Jsoup.parse(s1);
            Element jqLouPanBiao = parse1.getElementById("jqLouPanBiao");
            // 获取最大单元数
            Element thead = jqLouPanBiao.getElementsByTag("thead").get(0);
            Element tr3 = thead.getElementsByTag("tr").get(0);
            Elements colspan = tr3.getElementsByAttribute("colspan");
            // 最大单元数
            String maxUnit = colspan.get(colspan.size() - 1).text();

            Element tbody = jqLouPanBiao.getElementsByTag("tbody").get(0);
            Elements rowspan = tbody.getElementsByAttribute("rowspan");
            // 获取每套房详情
            for (Element element2 : rowspan) {
                String aClass = element2.attr("class");
                // 房屋状态
                String houseStatus = null;
                switch (aClass) {
                    case "sty_1":
                        houseStatus = "开发商-被查封或被限制销售的房产";
                        break;
                    case "sty_2":
                        houseStatus = "已抵押-被开发商抵押的房产";
                        break;
                    case "sty_3":
                        houseStatus = "已报审-已签约且申请备案的房产";
                        break;
                    case "sty_4":
                        houseStatus = "已备案-合同已备案的房产";
                        break;
                    case "sty_5":
                        houseStatus = "可销售-正常可销售的房产";
                        break;
                    case "sty_6":
                        houseStatus = "不可售-拆迁.集资.配套用房";
                        break;
                    default:
                }

                Elements a1 = element2.getElementsByTag("a");
                if (a1.size() <= 0) continue;
                String url3 = a1.get(0).attr("href");

                String url2 = URL_PREFIX + "/" + url3;

                // 房间详情页
                String s2 = httpClientInvoke(url2);
                Document parse2 = Jsoup.parse(s2);
                Element houseTable1 = parse2.getElementsByClass("house_table").get(0);
                Element tbody1 = houseTable1.getElementsByTag("tbody").get(0);
                Elements tr4 = tbody1.getElementsByTag("tr");
                // 当前幢号
                String building = tr4.get(1).getElementsByTag("td").get(3).text();
                // 房间号
                String doorTag = tr4.get(2).getElementsByTag("td").get(1).text();
                // 结构
                String structure = tr4.get(2).getElementsByTag("td").get(3).text();
                // 建筑面积
                String houseBuildArea = tr4.get(3).getElementsByTag("td").get(1).text();
                // 套内面积
                String dwellingSpace = tr4.get(3).getElementsByTag("td").get(3).text();
                // 分摊面积
                String sharedArea = tr4.get(4).getElementsByTag("td").get(1).text();
                // 房屋用途
                String houseUsing = tr4.get(4).getElementsByTag("td").get(3).text();
                // 所在层
                String inFloorNumber = tr4.get(5).getElementsByTag("td").get(1).text();
                // 总楼层
                String allFloorNumber = tr4.get(5).getElementsByTag("td").get(3).text();
                // 毛坯单价
                String roughcastUnitPrice = tr4.get(6).getElementsByTag("td").get(1).text();
                // 装修单价
                String renovationUnitPrice = tr4.get(6).getElementsByTag("td").get(3).text();
                // 户型
                String houseType = tr4.get(7).getElementsByTag("td").get(1).text();
                // 合同号
                String contractNumber = tr4.get(7).getElementsByTag("td").get(3).text();


                SpiderXinjianHousing xinjianHousing = new SpiderXinjianHousing();
                xinjianHousing.setSpiderLogId(spiderLogId);
                xinjianHousing.setPreId(preId);
                xinjianHousing.setDevCompany(spiderXinjianHousing.getDevCompany());
                xinjianHousing.setProjectName(spiderXinjianHousing.getProjectName());
                xinjianHousing.setProjectAreaName(spiderXinjianHousing.getProjectAreaName());
                xinjianHousing.setPassTime(spiderXinjianHousing.getPassTime());
                xinjianHousing.setUsing(using);
                xinjianHousing.setSalePhone(salePhone);
                xinjianHousing.setLandSource(landSource);
                xinjianHousing.setLandArea(landArea);
                xinjianHousing.setOccupationArea(occupationArea);
                xinjianHousing.setCommunityBuildArea(communityBuildArea);
                xinjianHousing.setLandLevel(landLevel);
                xinjianHousing.setPlotRatio(plotRatio);
                xinjianHousing.setGreenRatio(greenRatio);
                xinjianHousing.setBuildDensity(buildDensity);
                xinjianHousing.setProjectInvestment(projectInvestment);
                xinjianHousing.setStartProjectTime(startProjectTime);
                xinjianHousing.setEndProjectTime(endProjectTime);
                xinjianHousing.setConstructionUnit(constructionUnit);
                xinjianHousing.setMappingUnit(mappingUnit);
                xinjianHousing.setApproveHouseNumber(new Integer(approveHouseNumber));
                xinjianHousing.setApproveHouseArea(approveHouseArea);
                xinjianHousing.setInSaleHouseNumber(new Integer(inSaleHouseNumber));
                xinjianHousing.setInSaleHouseArea(inSaleHouseArea);
                xinjianHousing.setOutSaleHouseNumber(new Integer(outSaleHouseNumber));
                xinjianHousing.setOutSaleHouseArea(outSaleHouseArea);
                xinjianHousing.setApproveBusinessNumber(approveBusinessNumber);
                xinjianHousing.setApproveBusinessArea(approveBusinessArea);
                xinjianHousing.setInSaleBusinessNumber(inSaleBusinessNumber);
                xinjianHousing.setInSaleBusinessArea(inSaleBusinessArea);
                xinjianHousing.setOutSaleBusinessNumber(outSaleBusinessNumber);
                xinjianHousing.setOutSaleBusinessArea(outSaleBusinessArea);
                xinjianHousing.setApproveOfficeNumber(approveOfficeNumber);
                xinjianHousing.setApproveOfficeArea(approveOfficeArea);
                xinjianHousing.setInSaleOfficeNumber(inSaleOfficeNumber);
                xinjianHousing.setInSaleOfficeArea(inSaleOfficeArea);
                xinjianHousing.setOutSaleOfficeNumber(outSaleOfficeNumber);
                xinjianHousing.setOutSaleOfficeArea(outSaleOfficeArea);
                xinjianHousing.setApproveParkingNumber(approveParkingNumber);
                xinjianHousing.setApproveParkingArea(approveParkingArea);
                xinjianHousing.setInSaleParkingNumber(inSaleParkingNumber);
                xinjianHousing.setInSaleParkingArea(inSaleParkingArea);
                xinjianHousing.setOutSaleParkingNumber(outSaleParkingNumber);
                xinjianHousing.setOutSaleParkingArea(outSaleParkingArea);
                xinjianHousing.setApproveOtherNumber(approveOtherNumber);
                xinjianHousing.setApproveOtherArea(approveOtherArea);
                xinjianHousing.setInSaleOtherNumber(inSaleOtherNumber);
                xinjianHousing.setInSaleOtherArea(inSaleOtherArea);
                xinjianHousing.setOutSaleOtherNumber(outSaleOtherNumber);
                xinjianHousing.setOutSaleOtherArea(outSaleOtherArea);
                xinjianHousing.setBuilding(building);
                xinjianHousing.setUnitNumber(maxUnit);
                xinjianHousing.setAllFloorNumber(allFloorNumber);
                xinjianHousing.setInFloorNumber(inFloorNumber);
                xinjianHousing.setDoorTag(doorTag);
                xinjianHousing.setStructure(structure);
                xinjianHousing.setHouseStatus(houseStatus);
                xinjianHousing.setHouseBuildArea(houseBuildArea);
                xinjianHousing.setDwellingSpace(dwellingSpace);
                xinjianHousing.setSharedArea(sharedArea);
                xinjianHousing.setHouseUsing(houseUsing);
                xinjianHousing.setRoughcastUnitPrice(roughcastUnitPrice);
                xinjianHousing.setRenovationUnitPrice(renovationUnitPrice);
                xinjianHousing.setHouseType(houseType);
                xinjianHousing.setContractNumber(StringUtils.isBlank(contractNumber) ? null : contractNumber);
                xinjianHousing.setSaleStatus(saleStatus);

                log.info(xinjianHousing.toString());

                list.add(xinjianHousing);
            }
        }
    }

    private void saveCache(List<SpiderXinjianHousing> list) {
        for (SpiderXinjianHousing xinjianHousing : list) {
            redisMapper.leftPush(CACHE_NAME, xinjianHousing);
        }
    }

    @SneakyThrows
    public String httpClientInvoke(String url) {
        TimeUnit.SECONDS.sleep(SECOND_SLEEP_TIME);
        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9");
        httpGet.setHeader("Host", "59.53.216.196");
        httpGet.setHeader("Referer", url);
        httpGet.setHeader("Upgrade-Insecure-Requests", "1");
        httpGet.setHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36");
        CloseableHttpResponse response = httpClient.execute(httpGet);
        return EntityUtils.toString(response.getEntity());
    }
}
